//
// Created on 2024/11/28.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "PluginWindowRender.h"
#include "Log.h"
#include "PluginManager.h"
#include <sys/mman.h>
#include "camera_constants.h"
#include "native_buffer/native_buffer.h"

OH_NativeXComponent_Callback PluginWindowRender::m_callback;

PluginWindowRender::PluginWindowRender(std::string id, OH_NativeXComponent *nativeXComponent)
    : mId(id), viewWidth(640), viewHeight(480), mSurfaceWindow(nullptr), mSurfaceTransformState(TRANSFORM_IDENTITY) {
    registerComponent(nativeXComponent);
}
PluginWindowRender::~PluginWindowRender() {
    // 释放window窗口
    if (mSurfaceWindow) {
        OH_NativeWindow_DestroyNativeWindow(mSurfaceWindow);
        mSurfaceWindow = nullptr;
    }
}

void PluginWindowRender::registerComponent(OH_NativeXComponent *nativeXComponent) {
    if (!nativeXComponent) {
        return;
    }
    OH_NativeXComponent_Callback *renderCallback = &PluginWindowRender::m_callback;
    renderCallback->OnSurfaceChanged = onSurfaceChanged;     // surface刷新，可更新nativeWindow
    renderCallback->OnSurfaceCreated = onSurfaceCreated;     // surface创建，获取对应的nativeWindow
    renderCallback->OnSurfaceDestroyed = onSurfaceDestroyed; // surface销毁，释放资源
}

void PluginWindowRender::onSurfaceCreated(OH_NativeXComponent *component, void *window) {
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        return;
    }
    uint64_t width;
    uint64_t height;
    int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
    LOG_I("当前获取的窗口大小:%{public}lu*%{public}lu,%{public}d", width, height, xSize);
    if (xSize != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }
    std::string id(idStr);
    LOG_I("HomeNavigation onSurfaceCreated ID :%{public}s", idStr);
    auto *render = PluginManager::GetInstance()->getRender(id);
    LOG_I("HomeNavigation onSurfaceCreated render :%{public}d", render == nullptr);
    if (render == nullptr) {
        return;
    }
    render->initNativeWindow(window);
//     render->initOpenGL(window);
}
void PluginWindowRender::initNativeWindow(void *window) {
    OHNativeWindow *nativeWindow = static_cast<OHNativeWindow *>(window);
    if (nativeWindow) {
        this->mSurfaceWindow = nativeWindow;
        if (mSurfaceWindow) {
            int32_t ret =
                OH_NativeWindow_NativeWindowHandleOpt(mSurfaceWindow, SET_BUFFER_GEOMETRY, viewWidth, viewHeight);
            LOG_I("设置window窗口大小-结果:%{public}d", ret);
            initWindowOrientation();
        }
    }
}
void PluginWindowRender::onSurfaceChanged(OH_NativeXComponent *component, void *window) {
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        return;
    }
    std::string id(idStr);
    LOG_I("HomeNavigation onSurfaceCreated ID :%{public}s", idStr);
    auto *render = PluginManager::GetInstance()->getRender(id);
    LOG_I("HomeNavigation onSurfaceCreated render :%{public}d", render == nullptr);
    if (render == nullptr) {
        return;
    }
    render->initNativeWindow(window);
//     render->initOpenGL(window);
}
void PluginWindowRender::onSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) {
        return;
    }
    LOG_I("HomeNavigation onSurfaceDestroyed ID :%{public}s", idStr);
    std::string id(idStr);
    PluginManager::GetInstance()->removeComponent(id);
}

void PluginWindowRender::initSize(int width, int height) {
    this->viewWidth = width;
    this->viewHeight = height;
    if (mSurfaceWindow) {
        int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(mSurfaceWindow, SET_BUFFER_GEOMETRY, width, height);
        LOG_I("设置window窗口大小-结果:%{public}d", ret);
    }
}

bool PluginWindowRender::setSurfaceTransformState(int orientationState) {
    mSurfaceTransformState = orientationState;
    return initWindowOrientation();
}

bool PluginWindowRender::initWindowOrientation() {
    if (!this->mSurfaceWindow) {
        return false;
    }
    OH_NativeBuffer_TransformType rotationType;
    switch (mSurfaceTransformState) {
    case TRANSFORM_MIRROR_HORIZONTAL: // 水平镜像
        rotationType = NATIVEBUFFER_FLIP_H;
        break;
    case TRANSFORM_MIRROR_VERTICAL: // 垂直镜像
        rotationType = NATIVEBUFFER_FLIP_V;
        break;
    case TRANSFORM_ROTATE_90: // 旋转90度
        rotationType = NATIVEBUFFER_ROTATE_90;
        break;
    case TRANSFORM_ROTATE_180: // 旋转180度 = 水平镜像+垂直镜像
        rotationType = NATIVEBUFFER_ROTATE_180;
        break;
    case TRANSFORM_ROTATE_270: // 旋转270度 = 水平镜像 + 垂直镜像 + 旋转90度
        rotationType = NATIVEBUFFER_ROTATE_270;
        break;
    case TRANSFORM_FLIP_H_ROTATE_90: // 水平镜像 + 旋转90度;
        rotationType = NATIVEBUFFER_FLIP_H_ROT90;
        break;
    case TRANSFORM_FLIP_H_ROTATE_180: // 水平镜像 + 旋转180度 = 垂直镜像
        rotationType = NATIVEBUFFER_FLIP_H_ROT180;
        break;
    case TRANSFORM_FLIP_H_ROTATE_270: // 水平镜像 + 旋转270度 = 垂直镜像 + 旋转90度
        rotationType = NATIVEBUFFER_FLIP_H_ROT270;
        break;
    case TRANSFORM_FLIP_V_ROTATE_90: // 垂直镜像 + 旋转90度
        rotationType = NATIVEBUFFER_FLIP_V_ROT90;
        break;
    case TRANSFORM_FLIP_V_ROTATE_180: // 垂直镜像 + 旋转180度 = 水平镜像
        rotationType = NATIVEBUFFER_FLIP_V_ROT180;
        break;
    case TRANSFORM_FLIP_V_ROTATE_270: // 垂直镜像 + 旋转270度 = 水平镜像 + 旋转90度
        rotationType = NATIVEBUFFER_FLIP_V_ROT270;
        break;
    default:
        rotationType = NATIVEBUFFER_ROTATE_NONE; // 默认不使用图像变换
        break;
    }
    LOG_I("当前需要设置的方向:%{public}d", rotationType);
    int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(mSurfaceWindow, SET_TRANSFORM, rotationType);
    LOG_I("设置window窗口方向-结果:%{public}d", ret);
    return ret == 0;
}


bool PluginWindowRender::drawFrame(uint8_t *data, size_t dataSize, int w, int h) {
    if (!mSurfaceWindow || !data) {
        LOG_E("获取当前绘制的window窗口失败");
        return false;
    }

    OHNativeWindowBuffer *buffer = nullptr;
    int fenceFd;
    // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
    int ret = OH_NativeWindow_NativeWindowRequestBuffer(mSurfaceWindow, &buffer, &fenceFd);
    if (ret == 0 && buffer != nullptr) {
        BufferHandle *bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
        if (bufferHandle) {
            // 使用系统接口mmap将bufferHandle对应的共享内存映射到用户空间，可以通过映射出来的虚拟地址向bufferHandle中写入图像数据
            // bufferHandle->virAddr是bufferHandle在共享内存中的起始地址，bufferHandle->size是bufferHandle在共享内存中的内存占用大小
            void *mappedAddr = mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED,
                                    bufferHandle->fd, 0);
            if (mappedAddr != MAP_FAILED) {
                uint8_t *pixel = static_cast<uint8_t *>(mappedAddr); // 使用mmap获取到的地址来访问内存
                for (int i = 0, j = 0; i < w * h; ++i, j += 4) {
                    pixel[j] = data[i * 3 + 2];     // B
                    pixel[j + 1] = data[i * 3 + 1]; // G - G
                    pixel[j + 2] = data[i * 3];     // R
                    pixel[j + 3] = 0xFF;            // A
                }
                // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用，例如：显示在屏幕上。
                OH_NativeWindow_NativeWindowFlushBuffer(mSurfaceWindow, buffer, fenceFd, {nullptr, 0});
            }
            int result = munmap(mappedAddr, bufferHandle->size);
            if (result == -1) {
            }
        }
    }
    return true;
}